#include "brunnable.h"
#include "blog.h"

brunnable::~brunnable()
{
    // 析构时自动调用停止函数，防止外部忘记调用
	stop();
}

void brunnable::start()
{
    // 线程不存在，就创建线程
	if (!thread_)
		thread_ = std::make_unique<std::thread>(std::bind(&brunnable::thread_func, this));
}

void brunnable::stop()
{
    // 防止多次停止
	if (stop_) return;
	stop_ = true;
    // 唤醒线程，并等待线程结束
	thread_cv_.notify_all();
	if (thread_ && thread_->joinable())
		thread_->join();
}

void brunnable::push(std::shared_ptr<void> data)
{
    // 加锁，保护数据
	std::lock_guard<std::mutex> lck(mtx_);
    // 数据进入队列
	queue_.push(data);
    // 唤醒线程，处理数据
	thread_cv_.notify_one();
}

std::shared_ptr<void> brunnable::pop()
{
	std::shared_ptr<void> data;
    // 加锁，保护数据
	std::lock_guard<std::mutex> lck(mtx_);
	// 如果队列不为空，就取队列头数据返回
    if (!queue_.empty())
	{
		data = queue_.front();
		queue_.pop();
	}
	return data;
}

void brunnable::run()
{
    // 线程未停止情况下，循环读取数据
	while (!stop_)
	{
        // 每次将队列里的数据全部取出处理
		while (auto mp = pop())
		{
            // 子类实现数据处理函数
			handler(mp);
		}
        // 等待条件变量唤醒
		std::unique_lock<std::mutex> lk(mtx_);
		thread_cv_.wait(lk);
	}
}

void brunnable::thread_func()
{
    // 调用线程运行函数，多一个run函数调用，供子类可自定义重写run函数
	run();
}
